package com.iwhalecloud.citybrain.flow.platform.manager.application.common.command;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Objects;

import com.iwhalecloud.citybrain.flow.platform.manager.application.common.exception.CustomClientException;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.threadlocal.StartUserHolder;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpCreateProcessInstanceDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.User;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.common.impl.identity.Authentication;
import org.flowable.engine.common.impl.interceptor.Command;
import org.flowable.engine.common.impl.interceptor.CommandContext;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessInstanceHelper;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author lilh
 * @date 2019-02-12 15:54
 */
public class CreateProcessInstanceCmd implements Command<ProcessInstance>, Serializable {
    private static final long serialVersionUID = 4547252814498285323L;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private HttpCreateProcessInstanceDto createProcessInstanceDto;

    public CreateProcessInstanceCmd(HttpCreateProcessInstanceDto createProcessInstanceDto) {
        this.createProcessInstanceDto = createProcessInstanceDto;
    }

    @Override
    public ProcessInstance execute(CommandContext commandContext) {
        RepositoryService repositoryService = CommandContextUtil.getProcessEngineConfiguration(commandContext).getRepositoryService();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(createProcessInstanceDto.getFlowPackageCode()).latestVersion().active().singleResult();
        ProcessInstance processInstance = null;
        if (Objects.nonNull(processDefinition)) {

            try {
                StartUserHolder.setUser(resolveStarter(createProcessInstanceDto));

                //设置流程启动的发起人
                Authentication.setAuthenticatedUserId(createProcessInstanceDto.getParticipantId());
                ProcessInstanceHelper processInstanceHelper = CommandContextUtil.getProcessEngineConfiguration(commandContext).getProcessInstanceHelper();
                processInstance = processInstanceHelper.createProcessInstance(processDefinition, "isFromSdkCall", null, new HashMap<String, Object>(2){
                    private static final long serialVersionUID = 1206999924207634036L;

                    {
                        put("isFromSdkCall", true);
                    }
                }, null);
            } finally {
                StartUserHolder.remove();
            }
        } else {
            logger.warn("{}对应的流程定义不存在", createProcessInstanceDto.getFlowPackageCode());
            throw new CustomClientException(createProcessInstanceDto.getFlowPackageCode() + " 对应的流程定义不存在");
        }
        //设置第一个任务处理
        return processInstance;
    }

    private User resolveStarter(HttpCreateProcessInstanceDto createProcessInstanceDto) {
        User starter = new User();
        starter.setUserCode(createProcessInstanceDto.getParticipantId());
        starter.setUserName(createProcessInstanceDto.getParticipantName());
        starter.setUserId(starter.getUserCode());
        return starter;
    }
}
